package cn.tedu.charging.order.endpoint;

import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Component
@ServerEndpoint("/ws/server/{userId}")
@Slf4j
public class WebSocketServer {
    //作为一个终端 连接各种客户端发的请求,建立长连接
    //终端类要关注一个长连接的4个不同时间点,处理不同的业务

    //在用户连接之后，如果用户连接 不断 应该可以通过userId业务数据拿到每次他连接的session
    private static final Map<String,Session> SESSION_REGISTRY =
            new ConcurrentHashMap<>();

    /*
     * 1. 当某个客户端连接到服务器时调用
     * 可以接收参数
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId){
        log.info("有新的客户端连接");
        log.info("当前连接的终端sessionId:{}",session.getId());
        log.info("当前连接的终端用户id:{}",userId);
        //调用session api 成功建立连接 发送打招呼语句
        String message="你好,我是websocket终端服务器";
        try{
            RemoteEndpoint.Basic basicRemote = session.getBasicRemote();
            //推送字符串消息
            basicRemote.sendText(message);
        }catch (Exception e){
            log.error("发送打招呼语句失败",e);
        }
        //保存session 映射userId这个业务数据 放到map中
        SESSION_REGISTRY.put(userId,session);
        this.sendMsg2User(1,"你好 1号");
    }
    /*
     * 2. 当某个客户端关闭连接时调用
     * 可以接收参数
     */
    @OnClose
    public void onClose(Session session,@PathParam("userId") String userId){
        log.info("有客户端关闭连接");
        log.info("当前连接的终端sessionId:{}",session.getId());
        log.info("当前连接的终端用户id:{}",userId);
        //断开连接,从map中把数据移除
        SESSION_REGISTRY.remove(userId);
    }

    /*
     * 3. 当某个客户端发消息时调用
     * 可以接收参数
     */
    @OnMessage
    public void onMessage(String message,Session session,@PathParam("userId") String userId){
        log.info("有客户端发消息:{}", message);
        log.info("当前连接的终端sessionId:{}",session.getId());
        log.info("当前连接的终端用户id:{}",userId);
    }
    /*
     * 4. 当某个客户端异常关闭连接时调用
     */
    @OnError
    public void onError(Throwable error,Session session,@PathParam("userId") String userId){
        log.info("有客户端异常关闭连接",error);
        log.info("当前连接的终端sessionId:{}",session.getId());
        log.info("当前连接的终端用户id:{}",userId);
    }

    //准备一个该终端对象的推送消息给用户的方法 可以传递消息对象
    public static void sendMsg2User(Integer userId, String message){
        //1.通过userId 拿到这个用户连接的session
        Session session = SESSION_REGISTRY.get(userId);
        //2.用户建立连接后 有可能断开连接 注册里没有session 判断
        if (session!=null){
            try{
                session.getBasicRemote().sendText(message);
            }catch (Exception e){
                log.error("发送消息失败,userId:{},message:{}",userId,message,e);
            }
        }else{
            log.error("用户没有建立连接,userId:{},message:{}",userId,message);
        }
    }
}
